/*
 * Copyright (C) 2014 Miquel Sas
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package traderlib.core.data.entity;

import java.math.BigDecimal;
import java.util.List;
import traderlib.core.data.types.ByteArray;
import traderlib.core.data.types.Date;
import traderlib.core.data.types.Time;
import traderlib.core.data.types.Timestamp;
import traderlib.core.layout.Alignment;
import traderlib.core.data.types.Types;
import traderlib.core.data.types.Validator;
import traderlib.core.data.types.Value;
import traderlib.core.util.NumberUtils;
import traderlib.core.util.StringUtils;

/**
 * A Field packs the necessary information to define a data item, mainly in the form of tabular data.
 *
 * @author Miquel Sas
 */
public class Field implements Comparable<Object> {

	/**
	 * Field name.
	 */
	private String name = null;
	/**
	 * Optional field alias, if not set the name is used.
	 */
	private String alias = null;
	/**
	 * Length if applicable.
	 */
	private int length = -1;
	/**
	 * Decimals if applicable.
	 */
	private int decimals = -1;
	/**
	 * Type.
	 */
	private Types type = null;
	/**
	 * A flag that indicates is this field is a primary key field.
	 */
	private boolean primaryKey = false;
	/**
	 * A flag that indicates if this field is persistent.
	 */
	private boolean persistent = true;

	/**
	 * Maximum value.
	 */
	private Value maximumValue = null;
	/**
	 * Minimum value.
	 */
	private Value minimumValue = null;
	/**
	 * List of possible values.
	 */
	private List<Value> possibleValues = null;
	/**
	 * A flag indicating if a non empty value is required for this field.
	 */
	private boolean required = false;
	/**
	 * A flag indicating if this field can be null.
	 */
	private boolean nullable = true;
	/**
	 * A generic value validator.
	 */
	private Validator<Value> validator = null;
	/**
	 * Initial value.
	 */
	private Value initialValue = null;
	/**
	 * A flag to indicate if the field should initialize to the current date, time or time stamp.
	 */
	private boolean currentDateTimeOrTimestamp = false;

	/**
	 * Description, normally a longer description.
	 */
	private String description = null;
	/**
	 * Label on forms.
	 */
	private String label = null;
	/**
	 * Header on grids.
	 */
	private String header = null;
	/**
	 * Title or short description.
	 */
	private String title = null;

	/**
	 * Horizontal alignment.
	 */
	private Alignment horizontalAlignment = Alignment.Left;
	/**
	 * Vertical alignment.
	 */
	private Alignment verticalAlignment = Alignment.Center;
	/**
	 * Adjusted display length.
	 */
	private int displayLength = -1;
	/**
	 * Uppercase flag.
	 */
	private boolean uppercase = false;
	/**
	 * Minimum width, must be set for not autosize fields.
	 */
	private int minimumWidth = -1;
	/**
	 * Maximum width, must be set for not autosize fields.
	 */
	private int maximumWidth = -1;
	/**
	 * Preferred width, must be set for not autosize fields.
	 */
	private int preferredWidth = -1;
	/**
	 * Autosize flag.
	 */
	private boolean autoSize = true;
	/**
	 * Width factor for string fields.
	 */
	private double widthFactor = 0;
	/**
	 * Fixed size flag for form and table autosize.
	 */
	private boolean fixedWidth = true;

	/**
	 * Default constructor.
	 */
	public Field() {
		super();
	}

	/**
	 * Copy constructor.
	 *
	 * @param field The origin field to copy
	 */
	public Field(Field field) {
		super();
		// Definition attributes
		this.name = field.name;
		this.alias = field.alias;
		this.length = field.length;
		this.decimals = field.decimals;
		this.type = field.type;
		this.primaryKey = field.primaryKey;
		this.persistent = field.persistent;
		// Validation attributes
		this.maximumValue = field.maximumValue;
		this.minimumValue = field.minimumValue;
		this.possibleValues = field.possibleValues;
		this.required = field.required;
		this.nullable = field.nullable;
		this.validator = field.validator;
		// Initialization attributes
		this.initialValue = field.initialValue;
		this.currentDateTimeOrTimestamp = field.currentDateTimeOrTimestamp;
		this.description = field.description;
		this.label = field.label;
		this.header = field.header;
		this.title = field.title;
		// Layout attributes
		this.horizontalAlignment = field.horizontalAlignment;
		this.verticalAlignment = field.verticalAlignment;
		this.displayLength = field.displayLength;
		this.uppercase = field.uppercase;
		this.minimumWidth = field.minimumWidth;
		this.maximumWidth = field.maximumWidth;
		this.preferredWidth = field.preferredWidth;
		this.autoSize = field.autoSize;
		this.widthFactor = field.widthFactor;
		this.fixedWidth = field.fixedWidth;
	}

	/**
	 * Get the name.
	 *
	 * @return The name.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Set the name.
	 *
	 * @param name The name of the field.
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Get the field alias.
	 *
	 * @return The field alias.
	 */
	public String getAlias() {
		if (alias == null) {
			return getName();
		}
		return alias;
	}

	/**
	 * Set the field alias.
	 *
	 * @param alias The field alias.
	 */
	public void setAlias(String alias) {
		this.alias = alias;
	}

	/**
	 * Get the length.
	 *
	 * @return The field length if applicable.
	 */
	public int getLength() {
		return length;
	}

	/**
	 * Set the field length.
	 *
	 * @param length The field length.
	 */
	public void setLength(int length) {
		this.length = length;
	}

	/**
	 * Get the number of decimal places if applicable.
	 *
	 * @return The number of decimal places.
	 */
	public int getDecimals() {
		return decimals;
	}

	/**
	 * Set the number of decimal places.
	 *
	 * @param decimals The number of decimal places.
	 */
	public void setDecimals(int decimals) {
		this.decimals = decimals;
	}

	/**
	 * Get the type.
	 *
	 * @return The type.
	 */
	public Types getType() {
		return type;
	}

	/**
	 * Set the type.
	 *
	 * @param type The type.
	 */
	public void setType(Types type) {
		this.type = type;
		if (type.isString()) {
			setHorizontalAlignment(Alignment.Left);
		} else if (type.isNumber()) {
			setHorizontalAlignment(Alignment.Right);
		} else if (type.isBoolean()) {
			setHorizontalAlignment(Alignment.Center);
		} else {
			setHorizontalAlignment(Alignment.Left);
		}
	}

	/**
	 * Check if this field is a primary key field.
	 *
	 * @return A boolean
	 */
	public boolean isPrimaryKey() {
		return primaryKey;
	}

	/**
	 * Set if this field is a primary key field.
	 *
	 * @param primaryKey A boolean that indicates if this field is a primary key field.
	 */
	public void setPrimaryKey(boolean primaryKey) {
		this.primaryKey = primaryKey;
	}

	/**
	 * Check if this field is persistent.
	 *
	 * @return A boolean
	 */
	public boolean isPersistent() {
		return persistent;
	}

	/**
	 * Sets if this field is persistent.
	 *
	 * @param persistent A boolean.
	 */
	public void setPersistent(boolean persistent) {
		this.persistent = persistent;
	}

	/**
	 * Get the maximum value.
	 *
	 * @return The maximum value.
	 */
	public Value getMaximumValue() {
		return maximumValue;
	}

	/**
	 * Set the maximum value.
	 *
	 * @param maximumValue The maximum value.
	 */
	public void setMaximumValue(Value maximumValue) {
		validateValueType(maximumValue);
		this.maximumValue = maximumValue;
	}

	/**
	 * Get the minimum value.
	 *
	 * @return The minimum value.
	 */
	public Value getMinimumValue() {
		return minimumValue;
	}

	/**
	 * Set the minimum value.
	 *
	 * @param minimumValue The minimum value.
	 */
	public void setMinimumValue(Value minimumValue) {
		validateValueType(minimumValue);
		this.minimumValue = minimumValue;
	}

	/**
	 * Get the array of possible values.
	 *
	 * @return The array of possible values.
	 */
	public List<Value> getPossibleValues() {
		return possibleValues;
	}

	/**
	 * Set the array of possible values.
	 *
	 * @param possibleValues The array of possible values.
	 */
	public void setPossibleValues(List<Value> possibleValues) {
		if (possibleValues != null) {
			for (Value value : possibleValues) {
				validateValueType(value);
			}
		}
		this.possibleValues = possibleValues;
	}

	/**
	 * Check if a non empty value is required for this field.
	 *
	 * @return A boolean.
	 */
	public boolean isRequired() {
		return required;
	}

	/**
	 * Set if a non empty value is required for this field.
	 *
	 * @param required A boolean.
	 */
	public void setRequired(boolean required) {
		this.required = required;
	}

	/**
	 * Check if this field can be null.
	 *
	 * @return A boolean
	 */
	public boolean isNullable() {
		return nullable;
	}

	/**
	 * Set if this field can be null.
	 *
	 * @param nullable A boolean
	 */
	public void setNullable(boolean nullable) {
		this.nullable = nullable;
	}

	/**
	 * Get the generic validator.
	 *
	 * @return The generic validator.
	 */
	public Validator<Value> getValidator() {
		return validator;
	}

	/**
	 * Set the generic validator.
	 *
	 * @param validator The validator.
	 */
	public void setValidator(Validator<Value> validator) {
		this.validator = validator;
	}

	/**
	 * Validates the convinience of the argument value.
	 *
	 * @param value The value to validate.
	 * @return A boolean indicating if the value is valid.
	 */
	public boolean validate(Value value) {

		// Strict type
		if (!value.getType().equals(getType())) {
			return false;
		}

		// Maximum value
		if (getMaximumValue() != null) {
			if (value.compareTo(getMaximumValue()) > 0) {
				return false;
			}
		}

		// Minimum value
		if (getMinimumValue() != null) {
			if (value.compareTo(getMinimumValue()) < 0) {
				return false;
			}
		}

		// Possible values
		if (getPossibleValues() != null) {
			if (!value.in(getPossibleValues())) {
				return false;
			}
		}

		// Non empty required
		if (isRequired() && value.isEmpty()) {
			return false;
		}

		// Nullable
		if (!isNullable() && value.isNull()) {
			return false;
		}

		// Validator
		if (getValidator() != null) {
			return getValidator().validate(value);
		}

		return true;
	}

	/**
	 * Returns the validation message or null if validation is ok.
	 *
	 * @param value The value to check for the validation message.
	 * @return The validation message or null if validation is ok.
	 */
	public String getValidationMessage(Value value) {

		// Strict type
		if (!value.getType().equals(getType())) {
			StringBuilder b = new StringBuilder();
			b.append("Value type ");
			b.append(value.getType());
			b.append(" is not equals than this field type ");
			b.append(getType());
			return b.toString();
		}

		// Maximum value
		if (getMaximumValue() != null) {
			if (value.compareTo(getMaximumValue()) > 0) {
				StringBuilder b = new StringBuilder();
				b.append("Value ");
				b.append(value);
				b.append(" is greater than ");
				b.append(getMaximumValue());
				return b.toString();
			}
		}

		// Minimum value
		if (getMinimumValue() != null) {
			if (value.compareTo(getMinimumValue()) < 0) {
				StringBuilder b = new StringBuilder();
				b.append("Value ");
				b.append(value);
				b.append(" is than than ");
				b.append(getMinimumValue());
				return b.toString();
			}
		}

		// Possible values
		if (getPossibleValues() != null) {
			if (!value.in(getPossibleValues())) {
				StringBuilder b = new StringBuilder();
				b.append("Value ");
				b.append(value);
				b.append(" is not in the list of possible values");
				return b.toString();
			}
		}

		// Non empty required
		if (isRequired() && value.isEmpty()) {
			StringBuilder b = new StringBuilder();
			b.append("A non empty value is required for this field");
			return b.toString();
		}

		// Nullable
		if (!isNullable() && value.isNull()) {
			StringBuilder b = new StringBuilder();
			b.append("A not null value is required for this field");
			return b.toString();
		}

		// Validator
		if (getValidator() != null) {
			return getValidator().getValidationMessage(value);
		}

		return null;
	}

	/**
	 * Returns the default value padded with characters if it is string.
	 *
	 * @return The default blank value.
	 */
	public Value getBlankValue() {
		if (isString()) {
			return new Value(StringUtils.repeat(" ", getLength()));
		}
		return getDefaultValue();
	}

	/**
	 * Returns the default value for this field.
	 *
	 * @return The default value.
	 */
	public Value getDefaultValue() {
		if (isBoolean()) {
			return new Value(false);
		}
		if (isByteArray()) {
			return new Value(new ByteArray());
		}
		if (isDate()) {
			return new Value((Date) null);
		}
		if (isDecimal()) {
			return new Value(new BigDecimal(NumberUtils.defaultStringNumber(decimals)));
		}
		if (isDouble()) {
			return new Value((double)0);
		}
		if (isInteger()) {
			return new Value((int)0);
		}
		if (isLong()) {
			return new Value((long)0);
		}
		if(isString()) {
			return new Value("");
		}
		if (isTime()) {
			return new Value((Time)null);
		}
		if (isTimestamp()) {
			return new Value((Timestamp)null);
		}
		return null;
	}

	/**
	 * Get the initial value.
	 *
	 * @return The initial value.
	 */
	public Value getInitialValue() {
		return initialValue;
	}

	/**
	 * Set the initial value.
	 *
	 * @param initialValue The initial value.
	 */
	public void setInitialValue(Value initialValue) {
		validateValueType(initialValue);
		this.initialValue = initialValue;
	}

	/**
	 * Check if this field value should be initialized to the current date, time or timestamp.
	 *
	 * @return A boolean indicating the initialization rule.
	 */
	public boolean isCurrentDateTimeOrTimestamp() {
		return currentDateTimeOrTimestamp;
	}

	/**
	 * Check if his field should initialize to the current date.
	 * <p>
	 * @return A boolean indicating that it should be initialized to the current date.
	 */
	public boolean isCurrentDate() {
		return isDate() && isCurrentDateTimeOrTimestamp();
	}

	/**
	 * Check if his field should initialize to the current time.
	 * <p>
	 * @return A boolean indicating that it should be initialized to the current time.
	 */
	public boolean isCurrentTime() {
		return isTime() && isCurrentDateTimeOrTimestamp();
	}

	/**
	 * Check if his field should initialize to the current time stamp.
	 * <p>
	 * @return A boolean indicating that it should be initialized to the current time stamp.
	 */
	public boolean isCurrentTimestamp() {
		return isTimestamp() && isCurrentDateTimeOrTimestamp();
	}

	/**
	 * Set if this field value should be initialized to the current date, time or timestamp.
	 *
	 * @param currentDateTimeOrTimestamp A boolean.
	 */
	public void setCurrentDateTimeOrTimestamp(boolean currentDateTimeOrTimestamp) {
		this.currentDateTimeOrTimestamp = currentDateTimeOrTimestamp;
	}

	/**
	 * Get the long description.
	 *
	 * @return The long description.
	 */
	public String getDescription() {
		if (description == null) {
			if (title != null) {
				return title;
			}
			if (label != null) {
				return label;
			}
			if (header != null) {
				return header;
			}
		}
		return description;
	}

	/**
	 * Set the long description.
	 *
	 * @param description The long description.
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * Get the label used in forms.
	 *
	 * @return The label used in forms.
	 */
	public String getLabel() {
		if (label == null) {
			if (title != null) {
				return title;
			}
			if (header != null) {
				return header;
			}
		}
		return label;
	}

	/**
	 * Set the label used in forms.
	 *
	 * @param label The label used in forms.
	 */
	public void setLabel(String label) {
		this.label = label;
	}

	/**
	 * Get the header used in tables.
	 *
	 * @return The header used in tables.
	 */
	public String getHeader() {
		if (header == null) {
			if (label != null) {
				return label;
			}
			if (title != null) {
				return title;
			}
		}
		return header;
	}

	/**
	 * Set the header used in tables.
	 *
	 * @param header The header used in tables.
	 */
	public void setHeader(String header) {
		this.header = header;
	}

	/**
	 * Get the title or short description.
	 *
	 * @return The title or short description.
	 */
	public String getTitle() {
		if (title == null) {
			if (label != null) {
				return label;
			}
			if (header != null) {
				return header;
			}
			if (description != null) {
				return description;
			}
		}
		return title;
	}

	/**
	 * Set the title or short description.
	 *
	 * @param title The title or short description.
	 */
	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * Get the horizontal alignment.
	 *
	 * @return The horizontal alignment.
	 */
	public Alignment getHorizontalAlignment() {
		return horizontalAlignment;
	}

	/**
	 * Set the horizontal alignment.
	 *
	 * @param horizontalAlignment The horizontal alignment.
	 */
	public void setHorizontalAlignment(Alignment horizontalAlignment) {
		this.horizontalAlignment = horizontalAlignment;
	}

	/**
	 * Get the vertical alignment.
	 *
	 * @return The vertical alignment.
	 */
	public Alignment getVerticalAlignment() {
		return verticalAlignment;
	}

	/**
	 * Set the vertical alignment.
	 *
	 * @param verticalAlignment The vertical alignment.
	 */
	public void setVerticalAlignment(Alignment verticalAlignment) {
		this.verticalAlignment = verticalAlignment;
	}

	/**
	 * Get the display length.
	 *
	 * @return The display length.
	 */
	public int getDisplayLength() {
		return displayLength;
	}

	/**
	 * Set the display length.
	 *
	 * @param displayLength The display length.
	 */
	public void setDisplayLength(int displayLength) {
		this.displayLength = displayLength;
	}

	/**
	 * Check if edition is uppercase.
	 *
	 * @return A boolean
	 */
	public boolean isUppercase() {
		return uppercase;
	}

	/**
	 * Set if edition is uppercase.
	 *
	 * @param uppercase A boolean indicating that the value is uppercase.
	 */
	public void setUppercase(boolean uppercase) {
		this.uppercase = uppercase;
	}

	/**
	 * Get the minimum width.
	 *
	 * @return The minimum width.
	 */
	public int getMinimumWidth() {
		return minimumWidth;
	}

	/**
	 * Set the minimum width.
	 *
	 * @param minimumWidth The minimum width.
	 */
	public void setMinimumWidth(int minimumWidth) {
		this.minimumWidth = minimumWidth;
	}

	/**
	 * Get the maximum width.
	 *
	 * @return The maximum width.
	 */
	public int getMaximumWidth() {
		return maximumWidth;
	}

	/**
	 * Set the maximum width.
	 *
	 * @param maximumWidth The maximum width.
	 */
	public void setMaximumWidth(int maximumWidth) {
		this.maximumWidth = maximumWidth;
	}

	/**
	 * Get the preferred width.
	 *
	 * @return The preferred width.
	 */
	public int getPreferredWidth() {
		return preferredWidth;
	}

	/**
	 * Set the preferred width.
	 *
	 * @param preferredWidth The preferred width.
	 */
	public void setPreferredWidth(int preferredWidth) {
		this.preferredWidth = preferredWidth;
	}

	/**
	 * Check if the field is auto-size. Auto-size fields automatically calculate the necessary display with.
	 *
	 * @return A boolean.
	 */
	public boolean isAutoSize() {
		return autoSize;
	}

	/**
	 * Segt the auto-size flag.
	 *
	 * @param autoSize A boolean
	 */
	public void setAutoSize(boolean autoSize) {
		this.autoSize = autoSize;
	}

	/**
	 * Get the width factor to increase the calculated average width necessary to display the field in a form.
	 *
	 * @return The width factor.
	 */
	public double getWidthFactor() {
		return widthFactor;
	}

	/**
	 * Set the width factor to increase the calculated average width necessary to display the field in a form.
	 *
	 * @param widthFactor The width factor.
	 */
	public void setWidthFactor(double widthFactor) {
		this.widthFactor = widthFactor;
	}

	/**
	 * Check if the field is fixed with. Non fixed width fields expand to the width of the form or the maximum available
	 * width in a table.
	 *
	 * @return A boolean indicating if the field is fixed-width.
	 */
	public boolean isFixedWidth() {
		return fixedWidth;
	}

	/**
	 * Set if the field is fixed witdh.
	 *
	 * @param fixedWidth A boolean
	 */
	public void setFixedWidth(boolean fixedWidth) {
		this.fixedWidth = fixedWidth;
	}

	/**
	 * Returns a negative integer, zero, or a positive integer as this value is less than, equal to, or greater than the
	 * specified value.
	 * <p>
	 * A field is considered to be equal to another field if the alias, type, length and decimals are the same.
	 *
	 * @param o The object to compare.
	 * @return The compartion integer.
	 */
	@Override
	public int compareTo(Object o) {
		Field field = null;
		try {
			field = (Field) o;
		} catch (ClassCastException exc) {
			throw new UnsupportedOperationException("Not comparable type: " + o.getClass().getName());
		}
		if (getAlias().equals(field.getAlias())) {
			if (getType().equals(field.getType())) {
				if (getLength() == field.getLength()) {
					if (getDecimals() == field.getDecimals()) {
						return 0;
					}
				}
			}
		}
		return getAlias().compareTo(field.getAlias());
	}

	/**
	 * Returns the hash code for this field.
	 *
	 * @return The hash code
	 */
	@Override
	public int hashCode() {
		int hash = 3;
		return hash;
	}

	/**
	 * Check wheter the argument object is equal to this field.
	 *
	 * @param obj The object to compare
	 * @return A boolean.
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		final Field field = (Field) obj;
		return getAlias().equals(field.getAlias()) && getName().equals(field.getName());
	}

	/**
	 * Validates that the type of the argument value is valid for this field.
	 *
	 * @param value The value to validate.
	 */
	private void validateValueType(Value value) {
		if ((isBoolean() && !value.isBoolean())
				|| (isDateTimeOrTimestamp() && !value.isDateTimeOrTimestamp())
				|| (isString() && !value.isString())
				|| (isNumber() && !value.isNumber())) {
			throw new IllegalArgumentException("Invalid type " + value.getType() + " for this field type " + getType());
		}
	}

	/**
	 * Check if this field is boolean.
	 *
	 * @return A boolean.
	 */
	public boolean isBoolean() {
		return getType().isBoolean();
	}

	/**
	 * Check if this field is a string.
	 *
	 * @return A boolean.
	 */
	public boolean isString() {
		return getType().isString();
	}

	/**
	 * Check if this field is a number (decimal) with fixed precision.
	 *
	 * @return A boolean.
	 */
	public boolean isDecimal() {
		return getType().isDecimal();
	}

	/**
	 * Check if this field is a double.
	 *
	 * @return A boolean.
	 */
	public boolean isDouble() {
		return getType().isDouble();
	}

	/**
	 * Check if this field is an integer.
	 *
	 * @return A boolean.
	 */
	public boolean isInteger() {
		return getType().isInteger();
	}

	/**
	 * Check if this field is a long.
	 *
	 * @return A boolean.
	 */
	public boolean isLong() {
		return getType().isLong();
	}

	/**
	 * Check if this field is a number (decimal, double or integer).
	 *
	 * @return A boolean.
	 */
	public boolean isNumber() {
		return getType().isNumber();
	}

	/**
	 * Check if this field is a floating point number.
	 *
	 * @return A boolean.
	 */
	public boolean isFloatingPoint() {
		return getType().isFloatingPoint();
	}

	/**
	 * Check if this field is a date.
	 *
	 * @return A boolean.
	 */
	public boolean isDate() {
		return getType().isDate();
	}

	/**
	 * Check if this field is a time.
	 *
	 * @return A boolean.
	 */
	public boolean isTime() {
		return getType().isTime();
	}

	/**
	 * Check if this field is a time.
	 *
	 * @return A boolean.
	 */
	public boolean isTimestamp() {
		return getType().isTimestamp();
	}

	/**
	 * Check if this field is a date, time or timestamp.
	 *
	 * @return A boolean.
	 */
	public boolean isDateTimeOrTimestamp() {
		return getType().isDateTimeOrTimestamp();
	}

	/**
	 * Check if this field is binary (byte[]).
	 *
	 * @return A boolean.
	 */
	public boolean isByteArray() {
		return getType().isTimestamp();
	}

}
